#include "lib_standard.fxh"

struct tPixelShaderInput {

	float4 hposition;
	float3 position_os;
	float3 position_ws;
	float4 uv12;
	float4 uv34;
	float deformation;
	float3 normal;
	float3 tangent;
	float4 color;
};

void Vertex_Shader(float3 position, float3 normal,float3 tangent, float2 uv1, float2 uv2, float2 uv3, float2 uv4,
				  float4 color, float deformation, out tPixelShaderInput dataOut);

void Instance_Vertex_Shader(float3 position, float3 normal,float3 tangent, float instanceScale, float3 instanceRotate, float3 instancePosition, float2 uv1, float2 uv2, float2 uv3, float2 uv4,
				  float4 color, float deformation, out tPixelShaderInput dataOut);

void Pixel_Shader(float3 position_os, float3 position_ws, float3 normal,float3 tangnet, float2 uv1, float2 uv2, float2 uv3, float2 uv4,
				  float4 color, float deformation, float pixelDepth, out float4 outColor);

/*************************************************************************************
Vertex Shader Wrapper
**************************************************************************************/
void vs(

/*
Vertex Shader Input
*/
#ifdef VERTEX_POSITION
	#ifdef D3D9_IMPL 
		float3 position : POSITION
	#else
		float3 position : SV_Position
	#endif
#endif

#ifdef VERTEX_NORMAL
	,float3 normal : NORMAL
#endif

#ifdef VERTEX_COLOR
	,float4 color : COLOR
#endif

#ifdef VERTEX_TANGENT
	,float3 tangnet : TEXCOORD0
#endif

#ifdef VERTEX_UV1
	,float2 uv1 : TEXCOORD1
#endif

#ifdef VERTEX_UV2
	,float2 uv2 : TEXCOORD2
#endif

#ifdef VERTEX_UV3
	,float2 uv3 : TEXCOORD3
#endif

#ifdef VERTEX_UV4
	,float2 uv4 : TEXCOORD4
#endif

#ifdef VERTEX_DEFORMATION
	,float2 deformation : TEXCOORD5
#endif

/*
Vertex Shader Output
*/
#ifdef VERTEX_POSITION

	#ifdef D3D9_IMPL 
		,out float4 out_position : POSITION
	#else
		,out float4 out_position : SV_Position
	#endif
#endif

#ifdef VERTEX_COLOR
	,out float4 out_color : COLOR
#endif

#ifdef VERTEX_POSITION
	,out float3 out_position_os : TEXCOORD0
	,out float3 out_position_ws : TEXCOORD1
#endif
	
#if defined(VERTEX_UV1)
	,out float4 out_uv12 : TEXCOORD2
#elif defined(VERTEX_UV2)
	,out float4 out_uv12 : TEXCOORD2
#endif

#if defined(VERTEX_UV3)
	,out float4 out_uv34 : TEXCOORD3
#elif defined(VERTEX_UV4)
	,out float4 out_uv34 : TEXCOORD3
#endif

#ifdef VERTEX_DEFORMATION
	,out float2 out_deformation : TEXCOORD4
#endif

#ifdef VERTEX_NORMAL
	,out float3 out_normal : TEXCOORD5
#endif
	
#ifdef VERTEX_TANGENT
	,out float3 out_tangnet : TEXCOORD6
#endif
)
{
	
#ifndef VERTEX_POSITION
    float3 position	= (float3)0.0f;
#endif

#ifndef VERTEX_NORMAL
	float3 normal	= (float3)0.0f;
#endif

#ifndef VERTEX_TANGENT
	float3 tangnet	= (float3)0.0f;
#endif

#ifndef VERTEX_UV1
	float2 uv1 = (float2)0.0f;
#endif

#ifndef VERTEX_UV2
	float2 uv2 = (float2)0.0f;
#endif

#ifndef VERTEX_UV3
	float2 uv3 = (float2)0.0f;
#endif

#ifndef VERTEX_UV4
	float2 uv4 = (float2)0.0f;
#endif

#ifndef VERTEX_COLOR
	float4 color = (float4)1.0f;
#endif

#ifndef VERTEX_DEFORMATION
	float2 deformation = (float2)0.0f;
#endif

	tPixelShaderInput dataOut;
	Vertex_Shader(position, normal, tangnet, uv1, uv2, uv3, uv4,
				color, deformation.x, dataOut);

#ifdef VERTEX_POSITION
    out_position	= dataOut.hposition;
	out_position_os	= dataOut.position_os;
	out_position_ws	= dataOut.position_ws;
#endif

#ifdef VERTEX_NORMAL
	out_normal	= dataOut.normal;
#endif

#ifdef VERTEX_TANGENT
	out_tangnet	= dataOut.tangent;
#endif

#ifdef VERTEX_UV1
	out_uv12.xy = dataOut.uv12.xy;
#endif

#ifdef VERTEX_UV2
	out_uv12.zw = dataOut.uv12.zw;
#endif

#ifdef VERTEX_UV3
	out_uv34.xy = dataOut.uv34.xy;
#endif

#ifdef VERTEX_UV4
	out_uv34.zw = dataOut.uv34.zw;
#endif

#ifdef VERTEX_COLOR
	out_color = dataOut.color;
#endif

#ifdef VERTEX_DEFORMATION
	out_deformation = dataOut.deformation.x;
#endif

}

/*************************************************************************************
Vertex Shader (Instanced) Wrapper
**************************************************************************************/
void vsi(
		   
/*
Vertex Shader Input
*/
#ifdef VERTEX_POSITION
	#ifdef D3D9_IMPL 
		float3 position : POSITION
	#else
		float3 position : SV_Position
	#endif
#endif

#ifdef VERTEX_NORMAL
	,float3 normal : NORMAL
#endif

#ifdef VERTEX_COLOR
	,float4 color : COLOR
#endif

#ifdef VERTEX_TANGENT
	,float3 tangnet : TEXCOORD0
#endif

#ifdef VERTEX_UV1
	,float2 uv1 : TEXCOORD1
#endif

#ifdef VERTEX_UV2
	,float2 uv2 : TEXCOORD2
#endif

#ifdef VERTEX_UV3
	,float2 uv3 : TEXCOORD3
#endif

#ifdef VERTEX_UV4
	,float2 uv4 : TEXCOORD4
#endif

#ifdef VERTEX_DEFORMATION
	,float2 deformation : TEXCOORD5
#endif

#ifdef VERTEX_INSTANCE_POSITION
	,float4 instancePosition : INST_POSITION
#endif

#ifdef VERTEX_INSTANCE_SCALE_ROTATE
	,float4 instanceScaleRotate : INST_SCALE_ROTATE
#endif

/*
Vertex Shader Output
*/
#ifdef VERTEX_POSITION

	#ifdef D3D9_IMPL 
		,out float4 out_position : POSITION
	#else
		,out float4 out_position : SV_Position
	#endif
#endif

#ifdef VERTEX_COLOR
	,out float4 out_color : COLOR
#endif

#ifdef VERTEX_POSITION
	,out float3 out_position_os : TEXCOORD0
	,out float3 out_position_ws : TEXCOORD1
#endif
	
#if defined(VERTEX_UV1)
	,out float4 out_uv12 : TEXCOORD2
#elif defined(VERTEX_UV2)
	,out float4 out_uv12 : TEXCOORD2
#endif

#if defined(VERTEX_UV3)
	,out float4 out_uv34 : TEXCOORD3
#elif defined(VERTEX_UV4)
	,out float4 out_uv34 : TEXCOORD3
#endif

#ifdef VERTEX_DEFORMATION
	,out float2 out_deformation : TEXCOORD4
#endif

#ifdef VERTEX_NORMAL
	,out float3 out_normal : TEXCOORD5
#endif
	
#ifdef VERTEX_TANGENT
	,out float3 out_tangnet : TEXCOORD6
#endif
)
{
		
#ifndef VERTEX_POSITION
    float3 position	= (float3)0.0f;
#endif

#ifndef VERTEX_NORMAL
	float3 normal	= (float3)0.0f;
#endif

#ifndef VERTEX_TANGENT
	float3 tangnet	= (float3)0.0f;
#endif

#ifndef VERTEX_UV1
	float2 uv1 = (float2)0.0f;
#endif

#ifndef VERTEX_UV2
	float2 uv2 = (float2)0.0f;
#endif

#ifndef VERTEX_UV3
	float2 uv3 = (float2)0.0f;
#endif

#ifndef VERTEX_UV4
	float2 uv4 = (float2)0.0f;
#endif

#ifndef VERTEX_COLOR
	float4 color = (float4)1.0f;
#endif

#ifndef VERTEX_DEFORMATION
	float2 deformation = (float2)0.0f;
#endif
	
#ifndef VERTEX_INSTANCE_SCALE_ROTATE
	float4 instanceScaleRotate = (float4)0.0f;
#endif

#ifndef VERTEX_INSTANCE_POSITION
	float4 instancePosition = (float4)0.0f;
#endif	

	tPixelShaderInput dataOut;
	float instanceScale = 1;
	float3 instanceRotation = 0;

	Instance_Vertex_Shader(position, normal, tangnet, instanceScale, instanceRotation.xyz, instancePosition.xyz, 
						uv1, uv2, uv3, uv4, color, deformation, dataOut);
	
#ifdef VERTEX_POSITION
    out_position	= dataOut.hposition;
	out_position_os	= dataOut.position_os;
	out_position_ws	= dataOut.position_ws;
#endif

#ifdef VERTEX_NORMAL
	out_normal	= dataOut.normal;
#endif

#ifdef VERTEX_TANGENT
	out_tangnet	= dataOut.tangent;
#endif

#ifdef VERTEX_UV1
	out_uv12.xy = dataOut.uv12.xy;
#endif

#ifdef VERTEX_UV2
	out_uv12.zw = dataOut.uv12.zw;
#endif

#ifdef VERTEX_UV3
	out_uv34.xy = dataOut.uv34.xy;
#endif

#ifdef VERTEX_UV4
	out_uv34.zw = dataOut.uv34.zw;
#endif

#ifdef VERTEX_COLOR
	out_color = dataOut.color;
#endif

#ifdef VERTEX_DEFORMATION
	out_deformation = dataOut.deformation.x;
#endif

}

/*************************************************************************************
Pixel Shader Wrapper
**************************************************************************************/
void ps(

/*
Pixel Shader Input
*/
#ifdef VERTEX_POSITION
	#ifdef D3D9_IMPL 
		float4 hposition : POSITION,
	#else
		float4 hposition : SV_Position,
	#endif
#endif

#ifdef VERTEX_COLOR
	float4 color : COLOR,
#endif

#ifdef VERTEX_POSITION
	float3 position_os : TEXCOORD0,
	float3 position_ws : TEXCOORD1,
#endif

#if defined(VERTEX_UV1)
	float4 uv12 : TEXCOORD2,
#elif defined(VERTEX_UV2)
	float4 uv12 : TEXCOORD2,
#endif

#if defined(VERTEX_UV3)
	float4 uv34 : TEXCOORD3,
#elif defined(VERTEX_UV4)
	float4 uv34 : TEXCOORD3,
#endif

#ifdef VERTEX_DEFORMATION
	float2 deformation : TEXCOORD4,
#endif

#ifdef VERTEX_NORMAL
	float3 normal : TEXCOORD5,
#endif

#ifdef VERTEX_TANGENT
	float3 tangent : TEXCOORD6,
#endif

/*
Pixel Shader Output
*/
#ifdef D3D9_IMPL 
    out float4 outColor : COLOR
#else
    out float4 outColor : SV_Target
#endif
	)
{
	
#ifndef VERTEX_POSITION
	float3 position_os	= (float3)0.0f;
	float3 position_ws	= (float3)0.0f;
#endif

#ifndef VERTEX_NORMAL
	float3 normal	= (float3)0.0f;
#endif

#ifndef VERTEX_TANGENT
	float3 tangent	= (float3)0.0f;
#endif

#ifndef VERTEX_UV1
	float2 uv1 = (float2)0.0f;
#else
	float2 uv1 = uv12.xy;
#endif

#ifndef VERTEX_UV2
	float2 uv2 = (float2)0.0f;
#else
	float2 uv2 = uv12.zw;
#endif

#ifndef VERTEX_UV3
	float2 uv3 = (float2)0.0f;
#else
	float2 uv3 = uv34.xy;
#endif

#ifndef VERTEX_UV4
	float2 uv4 = (float2)0.0f;
#else
	float2 uv4 = uv34.zw;
#endif

#ifndef VERTEX_COLOR
	float4 color = (float4)1.0f;
#endif

#ifndef VERTEX_DEFORMATION
	float2 deformation = (float2)0.0f;
#endif
	
#ifndef VERTEX_INSTANCE_SCALE_ROTATE
	float4 instanceScaleRotate = (float4)0.0f;
#endif

#ifndef VERTEX_INSTANCE_POSITION
	float4 instancePosition = (float4)0.0f;
#endif	
	
	Pixel_Shader(position_os, position_ws, normal, tangent, 
				uv1, uv2, uv3, uv4,
				color, deformation, hposition.z / hposition.w, outColor);

}

#ifdef D3D9_IMPL

technique Technique0
{
    pass Pass0
    {
		SrcBlend = 5;
		DestBlend = 6;
		AlphaBlendEnable = TRUE;
		VertexShader = compile vs_3_0 vs();
		PixelShader  = compile ps_3_0 ps();
    }
}

#else

struct tGSDataum {

#ifdef VERTEX_POSITION

	#ifdef D3D9_IMPL 
		float4 position : POSITION;
	#else
		float4 position : SV_Position;
	#endif
#endif

#ifdef VERTEX_COLOR
	float4 color : COLOR;
#endif

#ifdef VERTEX_POSITION
	float3 position_os : TEXCOORD0;
	float3 position_ws : TEXCOORD1;
#endif
	
#if defined(VERTEX_UV1)
	float4 uv12 : TEXCOORD2;
#elif defined(VERTEX_UV2)
	float4 uv12 : TEXCOORD2;
#endif

#if defined(VERTEX_UV3)
	float4 uv34 : TEXCOORD3;
#elif defined(VERTEX_UV4)
	float4 uv34 : TEXCOORD3;
#endif

#ifdef VERTEX_DEFORMATION
	float2 deformation : TEXCOORD4;
#endif

#ifdef VERTEX_NORMAL
	float3 normal : TEXCOORD5;
#endif
	
#ifdef VERTEX_TANGENT
	float3 tangnet : TEXCOORD6;
#endif

};

/********************************************************

Instance streaming definition

*********************************************************/
#ifdef INSTANCE_STREAMING

#include "default_instance.fxh"

technique10 Technique_Standard {

    pass Pass0 {
        SetVertexShader( CompileShader( vs_4_0, vs() ) );
		SetGeometryShader( ConstructGSWithSO( CompileShader( gs_4_0, gs_instancing() ), "TEXCOORD0.xyzw; TEXCOORD1.xyzw;" ) );
        SetPixelShader( NULL );
    }
}

/*********************************************************
No instance streaming definition
*********************************************************/
#else 

#ifdef VERTEX_DEFORMATION

int calcTriangleTessilation(tGSDataum p0, tGSDataum p1, tGSDataum p2) {

	return (p0.deformation.x + p1.deformation.x + p2.deformation.x) > 1 ? 2 : 0;	
}

float3 offsetEvaluator(float3 os_position, float3 os_normal) {

	return os_normal * 1 * float3(0,sin(0.125 * (os_position.x + Time)) + sin(os_position.x + Time * 0.5f) + cos(0.625 * (os_position.z + Time)),0) * 0.1;
}

struct tGSSO {

#ifdef VERTEX_POSITION

	#ifdef D3D9_IMPL 
		float4 position : POSITION;
	#else
		float4 position : SV_Position;
	#endif
#endif

#ifdef VERTEX_COLOR
	float4 color : COLOR;
#endif
	
#ifdef VERTEX_UV1
	float2 uv1 : TEXCOORD1;
#endif

#ifdef VERTEX_UV2
	float2 uv2 : TEXCOORD2;
#endif

#ifdef VERTEX_UV3
	float2 uv3 : TEXCOORD3;
#endif

#ifdef VERTEX_UV4
	float2 uv4 : TEXCOORD4;
#endif

	float2 deformation : TEXCOORD5;

#ifdef VERTEX_NORMAL
	float3 normal : NORMAL;
#endif
	
#ifdef VERTEX_TANGENT
	float3 tangnet : TEXCOORD0;
#endif
};

void subdivide(tGSSO a, tGSSO b, bool sample_offset, float frac, out tGSSO mp) {

	mp = (tGSSO)0;
	mp.deformation.x = max(a.deformation.x, b.deformation.x);
	mp.deformation.y = lerp(a.deformation.y, b.deformation.y, frac);
	
#ifdef VERTEX_NORMAL
	mp.normal = normalize( lerp(a.normal, b.normal, frac));
#endif

#ifdef VERTEX_POSITION
	
	mp.position = lerp(a.position ,b.position, frac);
	if(sample_offset)
		mp.position.xyz += offsetEvaluator(mp.position.xyz, mp.normal.xyz);
#endif
	
#ifdef VERTEX_COLOR
	mp.color =	lerp(a.color,  b.color, frac);
#endif

#ifdef VERTEX_UV1
	mp.uv1 = lerp(a.uv1, b.uv1, frac);
#endif

#ifdef VERTEX_UV2
	mp.uv2 = lerp(a.uv2, b.uv2, frac);
#endif

#ifdef VERTEX_UV3
	mp.uv3 = lerp(a.uv3, b.uv3, frac);
#endif

#ifdef VERTEX_UV4
	mp.uv4 = lerp(a.uv4 , b.uv4, frac);
#endif
	
#ifdef VERTEX_TANGENT
	mp.tangnet = normalize( lerp(a.tangnet + b.tangnet, frac));
#endif
}

void assign(tGSDataum a, out tGSSO mp) {

	mp = (tGSSO)0;
	mp.deformation = a.deformation;
#ifdef VERTEX_POSITION
	mp.position.xyz = a.position_os;
	mp.position.w = a.position.w;
#endif
	
#ifdef VERTEX_COLOR
	mp.color = a.color;
#endif

#ifdef VERTEX_UV1
	mp.uv1 = a.uv12.xy;
#endif

#ifdef VERTEX_UV2
	mp.uv2 = a.uv12.zw;
#endif

#ifdef VERTEX_UV3
	mp.uv3 = a.uv34.xy;
#endif

#ifdef VERTEX_UV4
	mp.uv4 = a.uv34.zw;
#endif

#ifdef VERTEX_NORMAL
	mp.normal = a.normal;
#endif
	
#ifdef VERTEX_TANGENT
	mp.tangnet = a.tangnet;
#endif
}

void emitTriangle(tGSSO targetTriangle[3], inout TriangleStream<tGSSO> tesselation) {

	tesselation.Append(targetTriangle[0]);
	tesselation.Append(targetTriangle[1]);
	tesselation.Append(targetTriangle[2]);
	tesselation.RestartStrip();
}

void tessilateTriangle(tGSSO baseTriangle[3], bool sampleoffset_ab, bool sampleoffset_bc, bool sampleoffset_ca, out tGSSO subdivA[3], out tGSSO subdivB[3], out tGSSO subdivC[3], out tGSSO subdivD[3]) {

	tGSSO mp_ab,mp_bc,mp_ca;

	subdivide(baseTriangle[0], baseTriangle[1], sampleoffset_ab, 0.5f, mp_ab);
	subdivide(baseTriangle[1], baseTriangle[2], sampleoffset_bc, 0.5f, mp_bc);
	subdivide(baseTriangle[2], baseTriangle[0], sampleoffset_ca, 0.5f, mp_ca);

	subdivA[0] = baseTriangle[0];
	subdivA[1] = mp_ab;
	subdivA[2] = mp_ca;

	subdivB[0] = mp_ab;
	subdivB[1] = baseTriangle[1];
	subdivB[2] = mp_bc;

	subdivC[0] = mp_bc;
	subdivC[1] = baseTriangle[2];
	subdivC[2] = mp_ca;

	subdivD[0] = mp_ab;
	subdivD[1] = mp_bc;
	subdivD[2] = mp_ca;
}

[maxvertexcount(48)]
void gs_tess_inital(triangleadj tGSDataum points[6], inout TriangleStream<tGSSO> tesselation)
{
	tGSSO a, b, c;
	assign(points[0], a);
	assign(points[2], b);
	assign(points[4], c);

	a.position.w =
	b.position.w =
	c.position.w = 1.0f;

	a.deformation.y =
	b.deformation.y =
	c.deformation.y = 0.0f;
	
	float tri_tess = ceil(points[0].deformation.x + points[2].deformation.x + points[4].deformation.x);
	if(tri_tess > 0.0f) {
	
		float adj_ab_tess = ceil(points[0].deformation.x + points[1].deformation.x + points[2].deformation.x);
		float adj_bc_tess = ceil(points[2].deformation.x + points[3].deformation.x + points[4].deformation.x);
		float adj_ca_tess = ceil(points[4].deformation.x + points[5].deformation.x + points[0].deformation.x);

		a.deformation.x =
		b.deformation.x =
		c.deformation.x = 2.0f;

		float ab_tess = min(adj_ab_tess, tri_tess);
		float bc_tess = min(adj_bc_tess, tri_tess);
		float ca_tess = min(adj_ca_tess, tri_tess);

		tGSSO baseTriangle[3] = {a, b, c};

		tGSSO st_a_0[3];
		tGSSO st_b_0[3];
		tGSSO st_c_0[3];
		tGSSO st_d_0[3];

		tessilateTriangle(baseTriangle, 
			false, false, false, //adj_ab_tess > 0.0f, adj_bc_tess > 0.0f, adj_ca_tess > 0.0f, 
			st_a_0, st_b_0, st_c_0, st_d_0);

		tGSSO st_a_1[3];
		tGSSO st_b_1[3];
		tGSSO st_c_1[3];
		tGSSO st_d_1[3];

		//////////////////////////////////////
		//Tessselate and emit triangle A
		tessilateTriangle(st_a_0, 
			adj_ab_tess > 0.0f, true, adj_ca_tess > 0.0f, 
			st_a_1, st_b_1, st_c_1, st_d_1);
		
		//Assign tessilation limits to vertices on AB border
		st_a_1[1].deformation.y = ab_tess;
		st_b_1[0].deformation.y = ab_tess;
		st_b_1[1].deformation.y = ab_tess;
		st_d_1[0].deformation.y = ab_tess;
		//Assign tessilation limits to vertices on CA border
		st_a_1[2].deformation.y = ca_tess;
		st_c_1[0].deformation.y = ca_tess;
		st_c_1[2].deformation.y = ca_tess;
		st_d_1[2].deformation.y = ca_tess;

		emitTriangle(st_a_1, tesselation);
		emitTriangle(st_b_1, tesselation);
		emitTriangle(st_c_1, tesselation);
		emitTriangle(st_d_1, tesselation);

		//////////////////////////////////////
		//Tessselate and emit triangle B
		tessilateTriangle(st_b_0, 
			adj_ab_tess > 0.0f, adj_bc_tess > 0.0f, true, 
			st_a_1, st_b_1, st_c_1, st_d_1);
		
		//Assign tessilation limits to vertices on AB border
		st_a_1[0].deformation.y = ab_tess;
		st_a_1[1].deformation.y = ab_tess;
		st_b_1[0].deformation.y = ab_tess;
		st_d_1[0].deformation.y = ab_tess;
		//Assign tessilation limits to vertices on BC border
		st_b_1[2].deformation.y = bc_tess;
		st_c_1[1].deformation.y = bc_tess;
		st_c_1[2].deformation.y = bc_tess;
		st_d_1[1].deformation.y = bc_tess;

		emitTriangle(st_a_1, tesselation);
		emitTriangle(st_b_1, tesselation);
		emitTriangle(st_c_1, tesselation);
		emitTriangle(st_d_1, tesselation);

		//////////////////////////////////////
		//Tessselate and emit triangle C
		tessilateTriangle(st_c_0, 
			adj_bc_tess > 0.0f, true, adj_ca_tess > 0.0f, 
			st_a_1, st_b_1, st_c_1, st_d_1);
	
		//Assign tessilation limits to vertices on AB border
		st_a_1[0].deformation.y = ca_tess;
		st_a_1[2].deformation.y = ca_tess;
		st_c_1[0].deformation.y = ca_tess;
		st_d_1[2].deformation.y = ca_tess;
		//Assign tessilation limits to vertices on BC border
		st_b_1[1].deformation.y = bc_tess;
		st_b_1[2].deformation.y = bc_tess;
		st_c_1[1].deformation.y = bc_tess;
		st_d_1[1].deformation.y = bc_tess;

		emitTriangle(st_a_1, tesselation);
		emitTriangle(st_b_1, tesselation);
		emitTriangle(st_c_1, tesselation);
		emitTriangle(st_d_1, tesselation);

		//////////////////////////////////////
		//Tessselate and emit triangle D
		tessilateTriangle(st_d_0, 
			true, true, true,
			st_a_1, st_b_1, st_c_1, st_d_1);
		
		//Assign tessilation limits to vertices on all borders
		st_a_1[0].deformation.y = ab_tess;
		st_b_1[1].deformation.y = bc_tess;
		st_c_1[2].deformation.y = ca_tess;
	
		emitTriangle(st_a_1, tesselation);
		emitTriangle(st_b_1, tesselation);
		emitTriangle(st_c_1, tesselation);
		emitTriangle(st_d_1, tesselation);
	}
	else {


		tesselation.Append(a);
		tesselation.Append(b);
		tesselation.Append(c);
		tesselation.RestartStrip();
	}
}

[maxvertexcount(12)]
void gs_tess_pass(uniform float pass_idx, triangle tGSDataum points[3], inout TriangleStream<tGSSO> tesselation)
{
	tGSSO a, b, c;
	assign(points[0], a);
	assign(points[1], b);
	assign(points[2], c);

	bool primary_subdivide = false;
	if(a.deformation.x + b.deformation.x + c.deformation.x > pass_idx + 5) {

		primary_subdivide = true;
	}
	else {

		a.deformation.y = 1.0f;
		b.deformation.y = 1.0f;
		c.deformation.y = 1.0f;
	}

	//Determine if this triangle needs further subdivision
	if(primary_subdivide) {

		bool ab_subdivide_offset = false;
		bool bc_subdivide_offset = false;
		bool ca_subdivide_offset = false;

		//Is this pair on the base triangle's edge?
		if(a.deformation.y != 0.0f && b.deformation.y != 0.0f) {
			//a.position.xyz += 2.5f;
			if(a.deformation.y < pass_idx)
				ab_subdivide_offset = true;
		}

		if(b.deformation.y != 0.0f && c.deformation.y != 0.0f) {
			//a.position.xyz += 2.5f;
			if(b.deformation.y < pass_idx)
				bc_subdivide_offset = true;
		}

		if(c.deformation.y != 0.0f && a.deformation.y != 0.0f) {
			//a.position.xyz += 2.5f;
			if(c.deformation.y < pass_idx)
				ca_subdivide_offset = true;
		}

		tGSSO ab, bc, ca;
		subdivide(a, b, ab_subdivide_offset, 0.5f, ab);
		subdivide(b, c, bc_subdivide_offset, 0.5f, bc);
		subdivide(c, a, ca_subdivide_offset, 0.5f, ca);
		
		tesselation.Append(a);
		tesselation.Append(ab);
		tesselation.Append(ca);
		tesselation.RestartStrip();

		tesselation.Append(ab);
		tesselation.Append(b);
		tesselation.Append(bc);
		tesselation.RestartStrip();

		tesselation.Append(bc);
		tesselation.Append(c);
		tesselation.Append(ca);
		tesselation.RestartStrip();

		tesselation.Append(ca);
		tesselation.Append(ab);
		tesselation.Append(bc);
		tesselation.RestartStrip();
	}
	else {
		
		tesselation.Append(a);
		tesselation.Append(b);
		tesselation.Append(c);
		tesselation.RestartStrip();
	}
}

#ifndef SO_FORMAT 
#error "A stream out format was expected"
#endif

#endif

technique10 Technique_Standard {

#ifdef VERTEX_DEFORMATION

    pass Pass0 {
        SetVertexShader( CompileShader( vs_4_0, vs() ) );
		SetGeometryShader( ConstructGSWithSO( CompileShader( gs_4_0, gs_tess_inital() ), SO_FORMAT ) );
        SetPixelShader( NULL );
    } 
    pass Pass1 {
        SetVertexShader( CompileShader( vs_4_0, vs() ) );
		SetGeometryShader( ConstructGSWithSO( CompileShader( gs_4_0, gs_tess_pass(1.0f) ), SO_FORMAT ) );
        SetPixelShader( NULL );
    }
	pass Pass2 {
        SetVertexShader( CompileShader( vs_4_0, vs() ) );
		SetGeometryShader( ConstructGSWithSO( CompileShader( gs_4_0, gs_tess_pass(2.0f) ), SO_FORMAT ) );
        SetPixelShader( NULL );
    }/*
    pass Pass3 {
        SetVertexShader( CompileShader( vs_4_0, vs() ) );
		SetGeometryShader( ConstructGSWithSO( CompileShader( gs_4_0, gs_tess_pass(3.0f) ), SO_FORMAT ) );
        SetPixelShader( NULL );
    }
	pass Pass4 {
        SetVertexShader( CompileShader( vs_4_0, vs() ) );
		SetGeometryShader( ConstructGSWithSO( CompileShader( gs_4_0, gs_tess_pass(4.0f) ), SO_FORMAT ) );
        SetPixelShader( NULL );
    }*/
    pass Pass5 {
        SetVertexShader( CompileShader( vs_4_0, vs() ) );
		SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_4_0, ps() ) );
        
        SetBlendState(DefaultBlend, float4(1.0f,1.0f,1.0f,1.0f), 0xffffffff);
        SetDepthStencilState(DefaultDepthStencil, 0);
		SetRasterizerState(DefaultRasterize);
    }  

#else 
    pass Pass0 {

        SetVertexShader( CompileShader( vs_4_0, vs() ) );
		SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_4_0, ps() ) );
        
        SetBlendState(DefaultBlend, float4(1.0f,1.0f,1.0f,1.0f), 0xffffffff);
        SetDepthStencilState(DefaultDepthStencil, 0);
		SetRasterizerState(DefaultRasterize);
    }  
#endif 
}

technique10 Technique_Instanced
{
    pass Pass0
    {
        SetVertexShader( CompileShader( vs_4_0, vsi() ) );
#ifdef VERTEX_DEFORMATION
	/*
	SetGeometryShader(	CompileShader( gs_4_0, gs() ) );
	*/
		SetGeometryShader( NULL );
#else
	SetGeometryShader( NULL );
#endif
        SetPixelShader( CompileShader( ps_4_0, ps() ) );
        
        SetBlendState(DefaultBlend, float4(1.0f,1.0f,1.0f,1.0f), 0xffffffff);
        SetDepthStencilState(DefaultDepthStencil, 0);
		SetRasterizerState(DefaultRasterize);
    }  
}

/*********************************************************
End instance stream out definition 
*********************************************************/
#endif	


#endif